#pragma once

#include <string>
#include <vector>
#include <deque>
#include <queue>
#include <set>
#include <json.hpp>
#include <cinatra.hpp>
#include <vector>
#include "asio_executor.hpp"
#include "room_data_define.hpp"



using namespace cinatra;
using namespace std;


namespace bz {
	class meet;
	class xd_client;
	class xd_room;


	

	class meet_room :public AsioExecutor {
	public:
		meet_room(asio::io_context& io ,meet* me,xd_client *mcu);

		~meet_room();
		void before_del();
		async_simple::coro::Lazy<void> init();
		async_simple::coro::Lazy<void> sync_room();


		void ws_ter_update(terminal* ter);
		void get_device_online_state();
		void ws_meet_update();
		void ws_poll_setting_update();

		json get_all_terminal_list();

		void meet_update();
		async_simple::coro::Lazy<void> start_meet();
		async_simple::coro::Lazy<void> end_meet();
		void smc_error(string &body);
		void error_msg(int no,const string& name="", const string& describe = "");
		void push_ws_msg(ws_msg_type type, json& data, const string& msg = "");
		void push_ws_msg(ws_msg_type type, const string& msg = "");
		void ter_in_meeting(terminal* ter);
		void ter_out_meeting(terminal* ter);

		 async_simple::coro::Lazy<void> hand_terminal(string action, string obj_id);
		 async_simple::coro::Lazy<void> muti_hand_terminal(string action, vector<string> obj_list);

		 //async_simple::coro::Lazy<void> clear_last_ter(terminal * cur_ter);
	

		 async_simple::coro::Lazy<void> hand_all_sound(const bool mute);

		 async_simple::coro::Lazy<void> roll(terminal* ter);


		 async_simple::coro::Lazy<void> choose(terminal* ter);


		 async_simple::coro::Lazy<void> choose_first();
		 async_simple::coro::Lazy<void> set_other_ter_init(terminal* ter);


		 async_simple::coro::Lazy<void> reinvite_all_ter();
		 async_simple::coro::Lazy<void> reinvite_ter(terminal* ter);

		 async_simple::coro::Lazy<void> change_layout(string default_layout, json device_list);
		 async_simple::coro::Lazy<void> cancle_layout(terminal* ter);

		 async_simple::coro::Lazy<void> hand_poll(string action);

		 async_simple::coro::Lazy<void> hand_ter_poll(string obj_id,bool is_use);

		 /*async_simple::coro::Lazy<string> get_snapshot(string obj_id,string direction,int max_width);
		 async_simple::coro::Lazy<json> get_terminal_detail(json &obj_ids);
		 async_simple::coro::Lazy<json> get_link_detail(json &obj_ids);*/
		 void update_poll_plan();
		 async_simple::coro::Lazy<void> hungup_link(string obj_id);
		 async_simple::coro::Lazy<void> recall_link(string obj_id,string mcu_type);
		 async_simple::coro::Lazy<void> remove_link(string obj_id);

		

		 async_simple::coro::Lazy<void> change_main(string obj_id);
		 async_simple::coro::Lazy<void> invite_sip_uri(string obj_id, string name, string uri,string parent_obj,int id,string protocol);
		 async_simple::coro::Lazy<void> invite_ter(json device_list);
		 async_simple::coro::Lazy<void> subscribe_terminal_detail(string obj_id,bool is_link);
		 async_simple::coro::Lazy<void> unsubscribe_terminal_detail();

		 void reload_poll_setting();
		 async_simple::coro::Lazy<void> update_poll_setting();
		 async_simple::coro::Lazy<void> ws_poll_setting_later();
		 async_simple::coro::Lazy<void> camera_control(string obj_id,string cmd,string action);
		 async_simple::coro::Lazy<json> get_terminal_detail(json obj_ids);

		 void ter_added(terminal* ter);
	protected:
		
	private:
		


		void load_device_from_db();
		void load_poll_from_db();
		

		void update_terminal_list();
		void init_all_mcu();
		void init_poll_plan();
		

		terminal* par_get_ter(string&);
		terminal* uri_get_ter(string&);
		terminal* id_get_ter(string&);




		void update_sort_list();

		async_simple::coro::Lazy<void> set_ter_layout(terminal* ter, string layout);

		void get_layout_num(int& num, const string& layout);

		void remove_ter(terminal* ter);
		async_simple::coro::Lazy<void> poll_timer();
		async_simple::coro::Lazy<void> on_poll();

		void on_child_room_end(terminal* ter, xd_room* child_room);
		async_simple::coro::Lazy<void> online_check_timer();
		async_simple::coro::Lazy<void> recall_timer();
		async_simple::coro::Lazy<void> check_ter_status();
		async_simple::coro::Lazy<void> on_auto_recall();

		async_simple::coro::Lazy<void> clear_child_room(xd_room* room);

		async_simple::coro::Lazy<void> on_start(xd_room* room);

		meet* meet_;

		unordered_map<string, terminal*> obj_terminal_map_;
		unordered_map<string, terminal*> sip_uri_terminal_map_;
		unordered_map<string, terminal*> parti_terminal_map_;
		unordered_map<string, terminal*> child_room_map_;
		set<xd_room*> child_room_set_;
		set<terminal*> layout_ter_set_;
		deque<poll_ter*> poll_list_;
		poll_ter* last_poll_ter_;

		set<int> poll_select_range_;
		set<int> broadcast_select_range_;
		set<int> layout_weight_set_;

		vector<terminal*> terminal_list_;

		vector<std::tuple<int, string, int, string, int, int, int, string,string,string,string,string>> inital_device_list_;
		vector<std::tuple<string, string, int, int, int>> inital_poll_list_;
		
		terminal* main_ter_;
		terminal* main_parent_;
		//terminal* last_hand_ter_;
		int meet_num_;
		int bind_width_;
		int last_weight_;
		int unnormal_wei_;
		int cospace_weight_;
		int parti_num_;

		uint8_t call_roster_index_;
		uint8_t call_info_index_;

		poll_plan poll_plan_;

		bool select_range_choose_;
		bool is_set_layout_;


		string show_mode_;

		string action_;

		xd_room* main_room_;
		meet_state non_state;
		json poll_list_json_;
		bool is_del_;
		bool is_ready_;
		friend class meet_controller;

		friend class serv_manage;
		friend class xd_room;
	};

}